#include <stdlib.h>
#include <sys/time.h>
#include <string.h>
#include <stdio.h>
#include <stddef.h>

#include <sys/socket.h>
#include <arpa/inet.h>
#include <netdb.h>

#include "nbc.h"

int  g_http_delay = 500;
char g_buf[500];
char g_url[80],g_page[80];

int create_tcp_socket();
char *get_ip(char *host);
char *build_get_query(char *host, char *page);
void usage();
char* httpClient(char* host, char* page);

#define PORT 80
#define USERAGENT "HTMLGET 1.0"

void writeHttp();


//===============================
void readConfig()
//===============================
{
  FILE  *in,*out;
  char  line[128];
  char temps[12];

  in = fopen("config.nab","r");
  if(in == NULL)
    {
      strcpy(g_url,   "localhost");
      strcpy(g_page,  "datlog/data/DLCollector.php");
 
      printf("Create config file\n");
      out = fopen("config.nab","w");
      fprintf(out,"URL:   %s\n",g_url);
      fprintf(out,"PAGE:  %s\n",g_page);
      fclose(out);
    }
  else
    {
      if(g_debug > 3)printf("Open config file\n");
      while (fgets(line,sizeof line,in) != NULL)
      {
            if(strstr(line,"URL:") != NULL)sscanf(line,"%s %s",temps,g_url);
            if(strstr(line,"PAGE:") != NULL)sscanf(line,"%s %s",temps,g_page);
      }
      fclose(in);
    } 
}


//===============================
char* httpClient(char* host, char* page)
//===============================
{
  struct sockaddr_in *remote;
  int sock;
  int tmpres;
  char *ip;
  char *get;
  char buf[BUFSIZ+1];

  //usage(host,page);
 
  sock = create_tcp_socket();
  ip = get_ip(host);
  //fprintf(stderr, "IP is %s\n", ip);
  remote = (struct sockaddr_in *)malloc(sizeof(struct sockaddr_in *));
  remote->sin_family = AF_INET;
  tmpres = inet_pton(AF_INET, ip, (void *)(&(remote->sin_addr.s_addr)));
  if( tmpres < 0)  
  {
    perror("Can't set remote->sin_addr.s_addr");
    exit(1);
  }else if(tmpres == 0)
  {
    fprintf(stderr, "%s is not a valid IP address\n", ip);
    exit(1);
  }
  remote->sin_port = htons(PORT);
 
  if(connect(sock, (struct sockaddr *)remote, sizeof(struct sockaddr)) < 0){
    perror("Could not connect");
    exit(1);
  }
  get = build_get_query(host, page);
  //fprintf(stderr, "Query is:\n<<START>>\n%s<<END>>\n", get);
 
  //Send the query to the server
  int sent = 0;
  while(sent < strlen(get))
  {
    tmpres = send(sock, get+sent, strlen(get)-sent, 0);
    if(tmpres == -1){
      perror("Can't send query");
      exit(1);
    }
    sent += tmpres;
  }
  //now it is time to receive the page
  memset(buf, 0, sizeof(buf));
  int htmlstart = 0;
  char * htmlcontent;
  while((tmpres = recv(sock, buf, BUFSIZ, 0)) > 0){
    if(htmlstart == 0)
    {
      /* Under certain conditions this will not work.
      * If the \r\n\r\n part is splitted into two messages
      * it will fail to detect the beginning of HTML content
      */
      htmlcontent = strstr(buf, "\r\n\r\n");
      if(htmlcontent != NULL){
        htmlstart = 1;
        htmlcontent += 4;
      }
    }else{
      htmlcontent = buf;
    }
    if(htmlstart){
      strcpy(g_buf,htmlcontent);
    }
 
    memset(buf, 0, tmpres);
  }
  if(tmpres < 0)
  {
    perror("Error receiving data");
  }
  free(get);
  free(remote);
  free(ip);
  close(sock);
  return g_buf;
}
//===============================
void usage(char* host, char* page)
//===============================
{
  fprintf(stderr, "USAGE: htmlget host=%s [page=%s]\n",host,page);
}
 
//=============================== 
int create_tcp_socket()
//===============================
{
  int sock;
  if((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0){
    perror("Can't create TCP socket");
    exit(1);
  }
  return sock;
}
 
//=============================== 
char *get_ip(char *host)
//===============================
{
  struct hostent *hent;
  int iplen = 15; //XXX.XXX.XXX.XXX
  char *ip = (char *)malloc(iplen+1);
  memset(ip, 0, iplen+1);
  if((hent = gethostbyname(host)) == NULL)
  {
    printf("ip:%s\n",host);
    herror("Can't get IP");
    exit(1);
  }
  if(inet_ntop(AF_INET, (void *)hent->h_addr_list[0], ip, iplen) == NULL)
  {
    perror("Can't resolve host");
    exit(1);
  }
  return ip;
}
 
char *build_get_query(char *host, char *page)
{
  char *query;
  char *getpage = page;
  char *tpl = "GET /%s HTTP/1.0\r\nHost: %s\r\nUser-Agent: %s\r\n\r\n";
  if(getpage[0] == '/'){
    getpage = getpage + 1;
    fprintf(stderr,"Removing leading \"/\", converting %s to %s\n", page, getpage);
  }
  // -5 is to consider the %s %s %s in tpl and the ending \0
  query = (char *)malloc(strlen(host)+strlen(getpage)+strlen(USERAGENT)+strlen(tpl)-5);
  sprintf(query, tpl, getpage, host, USERAGENT);
  return query;
}
//===============================
int processData(char* fname)
//===============================
{
  FILE  *in;
  char  line[128],ff[128],stemp[80];
  int mid=0,sid=0,checksum=99,temp;

  in = fopen(fname,"r");
  if(in == NULL)
  {
      //printf("No %s\n",fname);
      return(0);
  }
  while(fgets(g_ul_data,sizeof g_ul_data,in) != NULL)
  { 	    
     sscanf(g_ul_data,"%d %d %d",&mid,&sid,&checksum);
     temp = checksum - mid - sid;
     if(temp == 0)
     {
        if(mid == NABTON_DATA || mid == NABTON_INFO)
        {
           if(mid == NABTON_INFO)
           {
		     sprintf(stemp," %d",g_http_delay);
		     strcat(g_ul_data,stemp);
	       } 
	       writeHttp();	 
          if(g_debug > 1)printf("%s Content: %s",fname,g_ul_data);
        }
     }
     else
      if(g_debug >0)printf("Checksum error [%s] ",g_ul_data);
  }
  fclose(in);
}
//===============================
void delay(int t)
//===============================
{
  t = t*1000; // convert to ms
  usleep(t);
} 
//===============================
void readHttp(char* response)
//===============================
{
   char stemp[40];
   int action=0,sid,mid;
   
   if(g_debug > 1)printf("HTTP received:(%s)",response);
   strcpy(g_dl_data," ");
   //Http gateway actions
   if(strstr(response,"NBC_HTTP_DELAY") != NULL)
   {
	   sscanf(response,"%d %d %s %d",&mid,&sid,stemp,&g_http_delay);
	   if(g_debug > 0)printf("System Parameter NBC_HTTP_DELAY = %d ",g_http_delay);
   }
   if(strstr(response,"NBC_HTTP_DEBUG") != NULL)
   {
	   sscanf(response,"%d %d %s %d",&mid,&sid,stemp,&g_debug);
	   printf("NBC_HTTP_DEBUG = %d ",g_debug);
   }
   
   // General 
   if(strstr(response,"NBC_REPORT_CONF") != NULL)action = 1;
   //Serial gateway actions
   if(strstr(response,"NBC_SERIAL_DELAY") != NULL)action = 1;
   if(strstr(response,"NBC_SERIAL_DEBUG") != NULL)action = 1;
   //Serial device actions
   if(strstr(response,"NBC_DEVICE_DELAY") != NULL)action = 1;
   if(strstr(response,"NBC_STEPPER_CTRL") != NULL)action = 1;
   //if(strstr(response,"new nabton command") != NULL)action =1 ;
   if(action==1)
   {
       //sprintf(g_dl_data,"%s",response);
       strcpy(g_dl_data,response);
       //sprintf(g_dl_data,"down_%d",g_rrno);
       if(g_debug > 0)printf(" - %s ",g_dl_data);
   }
   //strcpy(response," ");
} 
//===============================
void writeFile()
//===============================
{
  FILE  *out;
  char fname[80];
  g_rrno++;
  if(g_rrno > MAX_RRNO)g_rrno = 0;
  sprintf(fname,"dl_data_%d.nbc",g_rrno);
  out = fopen(fname,"w");
  fprintf(out,"%s",g_dl_data);
  if(g_debug > 1)printf("HTTP to serial gwy:(%s)",g_dl_data);
  fclose(out);
  strcpy(g_dl_data," ");
} 
//===============================
int readFile()
//===============================
{
  FILE  *in;
  char  line[128],ff[128],syscmd[80];
  
  system("ls ul_data*.nbc > ul_flist.nbc 2>&1");
  
  in = fopen("ul_flist.nbc","r");
  if(in == NULL)
  {
      printf("No ul_flist.nbc\n");
      return(0);
  }
  while(fgets(line,sizeof line,in) != NULL)
  { 
     sscanf(line,"%s",ff);
     processData(ff);
     sprintf(syscmd,"rm -f %s",ff);
     system(syscmd);
  }
  fclose(in);

  return(1);
} 
//===============================
void writeHttp()
//===============================
{
  int checksum = 0;
  int mid,sid,nfloat,dev_delay,serial_gwy_delay,http_gwy_delay;
  float data;
  char page_tot[240];
  //int len = strlen(g_ul_data);
  //printf("len=%d\n",len);
  //if(len > 1)printf("b%s\n",g_ul_data);
  if(strstr(g_ul_data,"no data") == NULL)
  {
	  if(g_debug > 0)printf(" %s",g_ul_data);
	  sscanf(g_ul_data,"%d %d %d",&mid,&sid,&checksum);
	  if(checksum == sid + mid)
      {
		  if(mid == NABTON_DATA)
		  {
		    sscanf(g_ul_data,"%d %d %d %d %f",&mid,&sid,&checksum,&nfloat,&data);
		    sprintf(page_tot,"%s?mid=%d&sid=%d&data=%.3f",g_page,mid,sid,data);
		  }
		  if(mid == NABTON_INFO)
		  {
		    sscanf(g_ul_data,"%d %d %d %d %d %d",&mid,&sid,&checksum,&dev_delay,&serial_gwy_delay,&http_gwy_delay);
		    sprintf(page_tot,"%s?mid=%d&sid=%d&ddel=%d&sdel=%d&hdel=%d",g_page,mid,sid,dev_delay,serial_gwy_delay,http_gwy_delay);
		  }
        if(g_debug > 0)printf("%s %s ",g_url,page_tot);
        char* html = httpClient(g_url,page_tot);
	    readHttp(html);
	    writeFile();
      }
  }
  strcpy(g_ul_data,"no data");
} 
//===============================
int main(int argc, char **argv)
//===============================
{   
	
  readConfig();
  g_rrno = 0;
  printf("URL: %s  PAGE:%s\n",g_url,g_page);
  strcpy(g_ul_data,"no data");
  while(1)
  {
	  readFile();
	  //writeHttp();
	  //readHttp();
	  //writeFile();
	  if(g_debug > 0)printf("\n(%d,%d)",g_http_delay,g_debug);
	  delay(g_http_delay);
  }
  
}
